/* ***** BEGIN LICENSE BLOCK *****
 *
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 * 
 * The Original Code is CnCNet Server code, Released 30th December 2009.
 * 
 * The Initial Developers of the Original Code are
 * Adam Krock and John Sanderson. Portions created by
 * the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s): Adam Krock, John Sanderson.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 * 
 * ***** END LICENSE BLOCK *****/

using System;


namespace cncNetServerV2
{
	public class codec
	{
		public class packets
		{
			// Basic packet class
			public class packet
			{
				protected byte[] packetData;
				private System.IO.MemoryStream packetStream;
                private System.IO.BinaryReader packetReader;
				
				public packet()
				{
					// Start with empty array
					packetData = new byte[0];
					// Assign reference for memory reader
					packetStream = new System.IO.MemoryStream(packetData);
					// Assing reference for Binary reader
					packetReader = new System.IO.BinaryReader(packetStream);
				}
							
				// Adds a value to the packetData
				private void addValue(byte[] b)
				{
					// Copy old array
					byte[] tempOne = packetData;
					// Resize array to fit new value
					packetData = new byte[tempOne.Length + b.Length];
					// copy old values to the new array
						// If this is not first value, copy
					if(tempOne.Length > 0)
					{
						// Copy old set
						Array.Copy(tempOne, packetData, tempOne.Length);
						// Add new set to end				
						int tempTwo = 0;
							// Starting at end of current array
						for(int i=tempOne.Length;i<packetData.Length;i++)
						{
							// Copy contents from b to the end of packetData
							packetData[i] = b[tempTwo];
							tempTwo++;
						}
					}
					else
					{
						// If this is first value, copy byte directly to data
						packetData = b;
					}
				}
							
				// Add methods
				public void addByte(byte b)
				{
					addValue(new byte[]{b});
				}
				
				public void addShort(short s)
				{			
					addValue(BitConverter.GetBytes(s));
				}
				
				public void addUShort(ushort us)
				{
					addValue(BitConverter.GetBytes(us));
				}
				
				public void addInt(int i)
				{
					addValue(BitConverter.GetBytes(i));
				}
				
				public void addUInt(uint ui)
				{
					addValue(BitConverter.GetBytes(ui));
				}
				
				public void addLong(long l)
				{
					addValue(BitConverter.GetBytes(l));
				}
				
				public void addULong(ulong ul)
				{
					addValue(BitConverter.GetBytes(ul));
				}
				
				public void addString(string s)
				{
					if(byte.MaxValue > s.Length)
					{
					addByte((byte)s.Length);
					addValue(System.Text.ASCIIEncoding.ASCII.GetBytes(s));
					}
				}
				
				// Get methods		
				public byte getByte()
				{
					return packetReader.ReadByte();
				}
				
				public short getShort()
				{
					return packetReader.ReadInt16();
				}
				
				public ushort getUShort()
				{
					return packetReader.ReadUInt16();
				}
				
				public int getInt()
				{
					return packetReader.ReadInt32();
				}
				
				public uint getUInt()
				{
					return packetReader.ReadUInt32();
				}
				
				public long getLong()
				{
					return packetReader.ReadInt64();
				}
				
				public ulong getULong()
				{
					return packetReader.ReadUInt64();
				}
				
				public pString getString()
				{
					byte tempOne = getByte();
					byte[] tempTwo = packetReader.ReadBytes(tempOne);
					string tempThree = System.Text.ASCIIEncoding.ASCII.GetString(tempTwo);
					return new pString(tempOne,tempThree);
				}
				
				public byte[] getBytes()
				{
					return packetData;
				}
			}
			
			// String structure with byte header/length
			public struct pString
			{
				public byte myLength;
				public string myString;
				
				public pString(byte l, string s)
				{
					myLength = l;
					myString = s;
				}
			}
					
			// 1
			public class clientVersion : packet
			{
				public byte myId;
				public pString myVersion;
				
				public clientVersion(string s)
				{
					addByte(1);
					addString(s);
				}
				
				public clientVersion(byte[] b)
				{
					packetData = b;
					myId = getByte();
					myVersion = getString();
				}
			}
			
			// 2
			public class serverVersionReply : packet
			{
				public byte myId;
				public byte myResult;
				
				public serverVersionReply(string s)
				{
					addByte(2);
					addString(s);
				}
				
				public serverVersionReply(byte[] b)
				{
					packetData = b;
					myId = getByte();
					myResult = getByte();
				}
			}
			
			// 3
			public class clientLogin : packet
			{
				public byte myId;
				public pString myUserName;
				public pString myPassword;
				
				public clientLogin(string username, string password)
				{
					addByte(3);
					addString(username);
					addString(password);
				}
				
				public clientLogin(byte[] b)
				{
					packetData = b;
					myId = getByte();
					myUserName = getString();
					myPassword = getString();
				}
			}
			
			// 4
			public class serverLoginReply : packet
			{
				public byte myId;	
				public byte myResult;
				
				public serverLoginReply(byte result)
				{
					addByte(4);
					addByte(result);
				}
				
				public serverLoginReply(byte[] b)
				{
					packetData = b;
					myId = getByte();
					myResult = getByte();
				}
			}
			
			// 5
			public class clientUserInfo : packet
			{
				public byte myId;
				public pString myGame;
				public pString myComputerId;
				
				public clientUserInfo(string game, string id)
				{
					addByte(5);
					addString(game);
					addString(id);
				}
				
				public clientUserInfo(byte[] b)
				{
					packetData = b;
					myId = getByte();
					myGame = getString();
					myComputerId = getString();
				}
			}
			
			// 6
			public class serverGameProfile : packet
			{
				public byte myId;
				public pString mySessionId;
				public pString myProfileName;
				public pString myProfileUri;
				
				
				public serverGameProfile(string sid, string name, string uri)
				{
					addByte(6);
					addString(sid);
					addString(name);
					addString(uri);
				}
				
				public serverGameProfile(byte[] b)
				{
					packetData = b;
					myId = getByte();
					mySessionId = getString();
					myProfileName = getString();
					myProfileUri = getString();
				}
			}
			
			// 7
			public class clientRequestUserList : packet
			{
				public byte myId;
				public pString mySessionId;
				
				public clientRequestUserList(string sid)
				{
					addByte(7);
					addString(sid);
				}
				
				public clientRequestUserList(byte[] b)
				{
					packetData = b;
					myId = getByte();
					mySessionId = getString();
				}
			}
			
			// 8
			public class serverSendUserList : packet
			{
				public byte myId;
				public byte myUsers;
				public pString myUserList;
				
				public serverSendUserList(byte u, string s)
				{
					addByte(8);
					addByte(u);
					addString(s);
				}
				
				public serverSendUserList(byte[] b)
				{
					packetData = b;
					myId = getByte();
					myUsers = getByte();
					myUserList = getString();
					
				}
			}
			
			// 9
			public class clientSendMessage : packet
			{
				public byte myId;
				public pString mySessionId;
				public pString myMessage;
				
				
				public clientSendMessage(string id, string m)
				{
					addByte(9);
					addString(id);
					addString(m);
				}
				
				public clientSendMessage(byte[] b)
				{
					packetData = b;
					myId = getByte();
					mySessionId = getString();
					myMessage = getString();
					
				}
				
			}
							
		}
	}
}
